from django.core.exceptions import ValidationError
# from django.shortcuts import render, HttpResponse
import random
from utils.tencent.sms import send_sms_single
from django import forms
from web import models
from web.forms.bootstrap import BootStrapForm
from django.core.validators import RegexValidator
from django.conf import settings
from django_redis import get_redis_connection
from utils.encrypt import md5


# Create register views.
class RegisterModelForm(BootStrapForm, forms.ModelForm):
    # 重写默认字符串，就是把models里面的文件重写了
    # 今天就讲到这里，明天继续
    # validator验证器，label标签
    # 今天讲解的是在forms中重写表单字段。
    # 在ModelForm中可自定义没有的字段，也可以覆盖原有的字段

    username = forms.CharField(label='用户名')

    password = forms.CharField(label='密码',
                               min_length=8,
                               max_length=64,
                               error_messages={
                                   'min_length': "密码长度不能小于8个字符",
                                   'max_length': "密码长度不能大于64个字符"
                               },
                               widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '请输入您的密码'}))

    confirm_password = forms.CharField(label='确认密码',
                                       min_length=8,
                                       max_length=64,
                                       error_messages={
                                           'min_length': "重复密码长度不能小于8个字符",
                                           'max_length': "重复密码长度不能大于64个字符"
                                       },
                                       widget=forms.PasswordInput(
                                           attrs={'class': 'form-control', 'placeholder': '再次确认您的密码'}))
    mobile_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])

#   code = forms.CharField(label='验证码',widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': '请输入验证码'}))

    class Meta:
        model = models.UserInfo
        fields = ['username', 'email', 'password', 'confirm_password', 'mobile_phone']  # 暂时删除code

    def clean_username(self):
        username = self.cleaned_data['username']
        exists = models.UserInfo.objects.filter(username=username).exists()
        if exists:
            # raise ValidationError("用户名已经存在")
            self.add_error("username", "用户名已经存在")
        return username

    def clean_email(self):
        email = self.cleaned_data['email']
        exists = models.UserInfo.objects.filter(email=email).exists()
        if exists:
            raise ValidationError("邮箱已经存在")
        return email

    def clean_password(self):
        pwd = self.cleaned_data['password']
        # 加密 & 返回
        return md5(pwd)

    def clean_confirm_password(self):
        password = self.cleaned_data['password']
        confirm_password = md5(self.cleaned_data['confirm_password'])
        if password != confirm_password:
            raise ValidationError("密码不一致")
        return confirm_password

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data.get('mobile_phone')
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if exists:
            raise ValidationError("手机号已注册")
        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data['code']
        mobile_phone = self.cleaned_data['mobile_phone']
        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)
        if not redis_code:
            raise ValidationError("验证码已失效或者未发送，请重新发送")
        redis_str_code = redis_code.decode('utf-8')
        if code.strip() != redis_str_code:
            raise ValidationError("验证码错误，请重新输入")
        return code


# 验证号码，以及发送短信
class SendSmsForm(forms.Form):
    mobile_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_mobile_phone(self):
        """手机验证的钩子，输入的手机号"""

        tpl = self.request.GET.get("tpl")
        mobile_phone = self.cleaned_data['mobile_phone']

        # 校验tpl
        template_id = settings.TENCENT_SMS_TEMPLATE[tpl]

        if not template_id:
            raise ValidationError('短信模板错误')
        # 是不存在号码
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if tpl == 'login':
            if not exists:
                raise ValidationError("手机号不存在")
        else:
            if exists:
                # self.add_error()
                raise ValidationError('号码已存在')

        # 发短信
        code = random.randrange(1000, 9999)
        sms = send_sms_single(mobile_phone, template_id, [code, ])
        if sms['result'] != 0:
            raise ValidationError("发送短信失败，{}".format(sms["errmsg"]))
        # 验证码写入redis
        conn = get_redis_connection()
        conn.set(mobile_phone, code, ex=60 * 60 * 24 * 5)
        return mobile_phone


# 短信登陆
class LoginSMSForm(BootStrapForm, forms.Form):
    mobile_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])
    code = forms.CharField(label='验证码',
                           widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': '请输入验证码'}))

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        user_object = models.UserInfo.objects.filter(mobile_phone=mobile_phone).first()
        if not user_object:
            raise ValidationError("手机号不存在")

        return user_object

    def clean_code(self):
        code = self.cleaned_data['code']
        user_object = self.cleaned_data.get('mobile_phone')
        # 手机号不存在，验证码无需校验
        if not user_object:
            return code
        conn = get_redis_connection()
        redis_code = conn.get(user_object.mobile_phone)
        if not redis_code:
            raise ValidationError("验证码失效或未发生，请重新发送")
        redis_str_code = redis_code.decode("utf-8")

        if code.strip() != redis_str_code:
            raise ValidationError("验证码错误，请重新输入")
        return code


# 用户名密码登陆
class LoginUPForm(BootStrapForm, forms.Form):
    username = forms.CharField(label="邮箱或手机号")
    password = forms.CharField(label="密码", widget=forms.PasswordInput(render_value=True))
    code = forms.CharField(label="图片验证码")

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_password(self):
        pwd = self.cleaned_data['password']
        # 加密 & 返回
        # 这里没有加密
        return md5(pwd)

    def clean_code(self):
        input_code = self.cleaned_data['code']
        # 去session中获取验证码
        session_code = self.request.session.get('image_code')
        if not session_code:
            raise ValidationError('验证码已过期，请重新获取')
        if input_code.strip().upper() != session_code.strip().upper():
            raise ValidationError('验证码输入错误')
        return input_code
